package com.baomidou.ant.controller;

import com.baomidou.ant.entity.PvpInfo;
import com.baomidou.ant.entity.PvpMessage;
import com.baomidou.ant.entity.PvpRoom;
import com.baomidou.ant.service.IPvpInfoService;
import com.baomidou.ant.service.IPvpMessageService;
import com.baomidou.ant.service.IPvpRoomService;
import com.baomidou.ant.utils.MyStringUtils;
import com.baomidou.ant.utils.SpringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import javax.xml.ws.Action;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 *
 *  实时对战新方案
 *  题目使用fastjson转化为json字符串发送
 *
 **/

@ServerEndpoint("/websocket/{userId}")
@Component
public class WebSocketServer {
    private Session session ;
    static Log log = LogFactory. getLog (WebSocketServer. class );
    // 静态变量，用来记录当前在线连接数。
    private static int onlineCount = 0 ;
    //concurrent 包的线程安全 Set ，用来存放每个客户端对应的 MyWebSocket 对象。
    public static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    //接收的消息器
    public String userId;

    @Autowired
    private IPvpInfoService pvpInfoService;


    //打开游戏
    @OnOpen
    public void onOpen(Session session, @PathParam( "userId" ) String userId) {
        this.session = session;
        webSocketSet .add( this ); // 加入 set 中
        addOnlineCount (); // 在线数加 1
        log.info( "有新的玩家进入房间:" +userId+ ",当前在线人数为 "+ getOnlineCount ());
        this.userId =userId;
        //开始游戏
        openGame(userId);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam( "userId" ) String userId) {
        webSocketSet .remove( this ); // 从 set 中删除
        subOnlineCount (); // 在线数减 1
        this.userId=userId;
        //关闭游戏
        closeGame(userId);
        log .info( "有玩家退出！当前在线人数为" + getOnlineCount ());
    }

    /*
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息，一条一条执行
     */
    @OnMessage
    public void onMessage(String message) {
        //message=m;
        log .info( "收到来自" + userId +"的信息 :" +message);
        // 群发消息
        for (WebSocketServer item : webSocketSet ) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }



    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        System.out.println(message);
        this . session .getBasicRemote().sendText(message);
    }


    /**
     * 群发自定义消息
     * */
    public static void sendInfo(String message, @PathParam ( "userId" ) String userId) throws IOException {
        log .info( "推送消息到" +userId+ " ，推送内容 :" +message);
        for (WebSocketServer item : webSocketSet ) {
            try {
                // 这里可以设定只推送给这个 设备id 的，为 null 则全部推送
                if (userId== null ) {
                    item.sendMessage(message);
                } else if (item.userId.equals(userId)){
                    //往指定设备id发送队列信息
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                e.getMessage();
            }
        }
    }

    //获取在线人数
    public static synchronized int getOnlineCount() {
        return onlineCount ;
    }

    //增加在线人数
    public static synchronized void addOnlineCount() {
        WebSocketServer. onlineCount ++;
    }

    //减少在线人数
    public static synchronized void subOnlineCount() {
        WebSocketServer. onlineCount --;
    }

    //onOpen方法
    public void openGame(String userId){
        QueryWrapper<PvpRoom> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        //获取service
        IPvpRoomService pvpRoomService = SpringUtils.getBean("pvpRoomService");
        PvpRoom pvpRoom=pvpRoomService.getOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(pvpRoom)){
            pvpRoom.setConnectStatus("1");
            pvpRoomService.saveOrUpdate(pvpRoom);
        }
    }

    //onClose方法
    public void closeGame(String userId){
        //先改变在线状态
        QueryWrapper<PvpRoom> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        //获取service
        IPvpRoomService pvpRoomService = SpringUtils.getBean("pvpRoomService");
        PvpRoom pvpRoom=pvpRoomService.getOne(queryWrapper);
        if(ObjectUtils.isNotEmpty(pvpRoom)){
            pvpRoom.setConnectStatus("0");
            pvpRoomService.saveOrUpdate(pvpRoom);
        }
        //再自动拒绝所有消息
        QueryWrapper<PvpMessage> pvpMessageQueryWrapper =new QueryWrapper<>();
        pvpMessageQueryWrapper.eq("response_user",userId);
        //获取service
        IPvpMessageService pvpMessageService = SpringUtils.getBean("pvpMessageService");
        List<PvpMessage> messageList=pvpMessageService.list(pvpMessageQueryWrapper);

        if(messageList!=null&&messageList.size()>0){
            for(PvpMessage pvpMessage:messageList){
                pvpMessage.setStatus("2");
                pvpMessageService.saveOrUpdate(pvpMessage);
            }
        }
        //离开对战房间，再把对战状态该为0，且失败
        if(userId.contains(",")){
            List<Integer> idList=MyStringUtils.getNum(userId);
            QueryWrapper<PvpInfo> pvpInfoQueryWrapper =new QueryWrapper<>();
            String ids1=idList.get(0)+","+idList.get(1);
            String ids2=idList.get(1)+","+idList.get(0);
            queryWrapper.eq("ids",ids1).or().eq("ids",ids2);
            pvpInfoQueryWrapper.eq("status","1");
            //获取service
            IPvpInfoService pvpInfoService = SpringUtils.getBean("pvpInfoService");
            List<PvpInfo> infoList=pvpInfoService.list(pvpInfoQueryWrapper);
            if(infoList!=null&&infoList.size()>0){
                for(PvpInfo pvpInfo:infoList){
                    //退出的如果是发起者，则失败
                    if(pvpInfo.getUserId().equals(idList.get(0))){
                        pvpInfo.setStatus("0");
                        pvpInfo.setResult("败");
                    } else if(pvpInfo.getUserId().equals(idList.get(1))){
                        //如果被挑战者退出，则是胜利
                        pvpInfo.setStatus("0");
                        pvpInfo.setResult("胜");
                    }
                    pvpInfoService.saveOrUpdate(pvpInfo);
                }
            }
            //跑路，推送消息给对方
            String ids=idList.get(1)+","+idList.get(0);
            try {
                sendInfo("对方已经逃跑", ids);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
